package cn.edu.tsinghua.training.cms.demo.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;

import cn.edu.tsinghua.training.cms.demo.dao.GenericDao;
import cn.edu.tsinghua.training.cms.demo.util.PageBean;
//泛型化DAO接口的泛型化实现类
//实现通用的数据库方法
public class GenericDaoImpl<E extends Serializable, ID extends Serializable> implements GenericDao<E, ID> {

	@Autowired
	private SessionFactory sessionFactory;
	private Class<E> entityClass;
	
	@SuppressWarnings("unchecked")
	public GenericDaoImpl() {
		entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public ID add(E e) {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		ID id = (ID) session.save(e);
		transaction.commit();
		session.close();
		return id;
	}


	@SuppressWarnings("unchecked")
	@Override
	public List<E> query(String hql, String[] paramNames, Object[] values) {
		Session session = sessionFactory.openSession();
		Query query = session.createQuery(hql);
		if (paramNames != null && values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(paramNames[i], values[i]);
			}
		}
		List<E> list = query.list();
		session.close();
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<E> queryAll() {
		Session session = sessionFactory.openSession();
		Query query = session.createQuery("FROM " + entityClass.getName());
		List<E> list = query.list();
		session.close();
		return list;
	}

	@SuppressWarnings("unchecked")
	@Override
	public E queryById(ID id) {
		Session session = sessionFactory.openSession();
		E entity = (E) session.get(entityClass, id);
		session.close();
		return entity;
	}
	
	@Override
	public void update(E e) {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		session.update(e);
		transaction.commit();
		session.close();
	}
	
	@Override
	public void delete(E e) {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		session.delete(e);
		transaction.commit();
		session.close();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public PageBean queryForPage(String hql, String[] params, Object[] values, int pageSize, int page) {
		int allRow = getAllRowCount(hql, params, values);
		int totalPage = PageBean.countTotalPage(pageSize, allRow);
		page = (page>totalPage)?totalPage:page;
		int offset = PageBean.countOffset(pageSize, page);
		int length = pageSize;
		int currentPage = PageBean.countCurrentPage(page);
		
		Session session = sessionFactory.openSession();
		Query query = session.createQuery(hql).setFirstResult(offset).setMaxResults(length);//*****
		if (params != null && values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(params[i], values[i]);
			}
		}
		List<E> list = query.list();
		session.close();
		
		PageBean pageBean = new PageBean();
		pageBean.setPageSize(pageSize);
		pageBean.setCurrentPage(currentPage);
		pageBean.setAllRow(allRow);
		pageBean.setTotalPage(totalPage);
		pageBean.setList(list);
		pageBean.init();
		
		return pageBean;
	}
	
	@Override
	public int getAllRowCount(String hql, String[] params, Object[] values) {
		return query(hql, params, values).size();
	}
	
}
